package tom.vertx.core.demo05;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.http.ClientAuth;
import io.vertx.core.net.JdkSSLEngineOptions;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.net.OpenSSLEngineOptions;
import lombok.extern.slf4j.Slf4j;

/**
 * 对于同一个host:port启动多个实例,vertx做了特殊处理, 在已经启动了一个server或者instance情况下,
 * 不会在启动一个server,内部只维护一个server, 然后将接收到的请求以round-robin形式分发给connectionHandler,
 * 以此来提高多核利用率
 * @author ZHUFEIFEI
 */
@Slf4j
public class MyTcpServer extends AbstractVerticle {

  private boolean ssl;

  public MyTcpServer() {

  }

  public MyTcpServer(boolean ssl) {
    this.ssl = ssl;
  }

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    //port 0 random
    NetServerOptions netServerOptions = new NetServerOptions()
      //启用ssl
      .setSsl(this.ssl)
      .setClientAuth(ClientAuth.REQUIRED)
      .setKeyCertOptions(TcpDemo.keyCertOptions())
      .setTrustOptions(TcpDemo.trustOptions())
      //默认jdk, 可以使用openssl engine, 性能好于jdk
//      .setJdkSslEngineOptions(new JdkSSLEngineOptions())
//      .setOpenSslEngineOptions(new OpenSSLEngineOptions())
      //debug
      .setLogActivity(false)
      .setPort(8888);
    //verticle卸载时自动关闭, 为了充分利用多核,可以启动多个verticle实例, 通过setInstances,也可以自行启动多个server
    for (int i=0; i<3; i++) {
      NetServer server = vertx.createNetServer(netServerOptions)
        .exceptionHandler(exp -> {
          if (exp.getCause() != null) {
            exp.getCause().printStackTrace();
          } else {
            log.info("server error => {}", exp.toString());
          }
        })
        .connectHandler(res -> {
        log.info("new connection => {}", res.remoteAddress());
        res.handler(buffer -> {
          log.info("receive client request => {}", buffer.toString());
          res.write("ok!");
        });
      }).listen(res -> {
        if (res.succeeded()) {
          log.info("tcp server start => {}", res.result().actualPort());
        } else {
          log.info("tcp server start failed => {}", res.cause().toString());
        }
      });
    }
    startPromise.complete();

  }
}
